package blackberry.util.field;

import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Keypad;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.TouchEvent;
import net.rim.device.api.ui.container.HorizontalFieldManager;


/**
 * 팁 
 * 이상하게 화면을 터치하면 navigationClick()메소드가 같이 호출이 되는 현상 발생
 * 해결법 = status가 0인것을 걸러내면됨
 */

public class DjHighlightManager extends Manager {
	
	public static final int DEFAULT_FOCUSED_COLOR = Color.DODGERBLUE;
	public static final int DEFAULT_SELECTED_COLOR = Color.DEEPSKYBLUE;
	public static final int DEFAULT_GLOBAL_ALPHA = 150;
	public static final int NOT_INIT = -1;
	
	private int focusedColor;
	private int selectedColor;
	private int globalAlpha;
	
	private boolean focused;
	private boolean selected;
	private boolean enabled = true;
	

	private PaintField paintField;
	private Manager delegateManager;

	public DjHighlightManager() {
		this(NOT_INIT, NOT_INIT, NOT_INIT, null);
	}
	
	public DjHighlightManager(Manager delegateManager) {
		this(NOT_INIT, NOT_INIT, NOT_INIT, delegateManager);
	}
	
	public DjHighlightManager(int focusedColor, int globalAlpha, Manager delegateManager) {
		this(focusedColor, NOT_INIT, globalAlpha, null);
	}
	
	public DjHighlightManager(int focusedColor, int selectedColor, int globalAlpha,
			Manager delegateManager) {
		super(0);
		
		if (focusedColor == NOT_INIT)
			this.focusedColor = DEFAULT_FOCUSED_COLOR;
		else
			this.focusedColor = focusedColor;
		
		this.selectedColor = selectedColor;

		if (globalAlpha == NOT_INIT) 
			this.globalAlpha = DEFAULT_SELECTED_COLOR;
		else
			this.globalAlpha = globalAlpha;
		
		
		if (delegateManager == null)
			this.delegateManager = new HorizontalFieldManager();
		else
			this.delegateManager = delegateManager;
		
		paintField = new PaintField(this);
		
		super.add(paintField);
		super.add(this.delegateManager);
	}
	
	
	protected void sublayout(int maxWidth, int maxHeight) {
	
		setExtent(getPreferredWidth(), getPreferredHeight());
		
		setPositionChild(paintField, 
				0, 
				0);
		layoutChild(paintField, 
				getPreferredWidth(), 
				getPreferredHeight());
		
		setPositionChild(delegateManager, 
				0, 
				0);
		layoutChild(delegateManager, 
				getPreferredWidth(), 
				getPreferredHeight());
	}
	
	
	public int getPreferredWidth() {
		return delegateManager.getPreferredWidth();
	}
	public int getPreferredHeight() {
		return delegateManager.getPreferredHeight();
	}
	
	
	protected void onFocus(int direction) {
		super.onFocus(direction);
		focused = true;
		invalidate();
	}
	protected void onUnfocus() {
		super.onUnfocus();
		focused = false;
		selected = false;
		invalidate();
	}
	
	
	private void select() {
		selected = true;
		invalidate();
	}
	private void unSelect() {
		selected = false;
		invalidate();
	}

	
	public void add(Field field) {
		delegateManager.add(field);
	}
	public void delete(Field field) {
		delegateManager.delete(field);
	}
	

	//이유는 모르겠지만 keyDown이 반응을 안해서 keyUp만 활용 하였음
	protected boolean keyUp(int keycode, int time) {
		
		if (enabled == false)
			return false;
		
		if (isExecuteKey(keycode)) { 
			execute();
		}
		return super.keyUp(keycode, time);
	}
	protected boolean isExecuteKey(int keycode) {
		return Keypad.key(keycode) == Keypad.KEY_ENTER;
	}
	
	
	protected boolean navigationClick(int status, int time) {
	
		if (enabled == false || status == 0)
			return false;
		select();

		return super.navigationClick(status, time);
	}
	protected boolean navigationUnclick(int status, int time) {
		
		if (enabled == false || status == 0)
			return false;
		execute();
		unSelect();
		
		return super.navigationUnclick(status, time);
	}
	
	//Highlight가 커서로써의 기능이 없을때 오버라이드 해서 사용 할 수 있음
	//1.DOWN하면 포커스 켜짐
	//2.MOVE해서 필드 벗어나면 포커스 꺼짐
	//3.UP하면 포커스 꺼짐
	protected boolean touchEvent(TouchEvent message) {
		
		if (enabled == false || outOfBounds(message))
			return false;
		
		switch (message.getEvent()) {
		
		case TouchEvent.CLICK : 
			
			execute();
			break;
		}
		
		return super.touchEvent(message);
	}
	protected boolean outOfBounds(TouchEvent message){
		return message.getX(1) < 0 || message.getY(1) < 0 
				|| message.getX(1) > getPreferredWidth()
				|| message.getY(1) > getPreferredHeight();
	}
//	//Highlight가 커서로써의 기능이 없을때 오버라이드 해서 사용 할 수 있음
//	//1.DOWN하면 onFocus()가 호출되며 포커스 켜짐
//	//2.MOVE해서 필드 벗어나면 포커스 꺼짐
//	//3.UP하면 포커스 꺼짐
//	boolean touchDown;
//	protected boolean touchEvent(TouchEvent message) {
//		
//		if (enabled == false)
//			return false;
//		
//		switch (message.getEvent()) {
//		
//		case TouchEvent.DOWN : 
//			
//			if (outOfBounds(message))
//				return false;
//			
//			touchDown = true;
//			break;
//			
//		case TouchEvent.MOVE : 
//			
//			if (touchDown == false)
//				break;
//			
//			if (outOfBounds(message)) {
//				focused = false;
//				unSelect();
//				touchDown = false;
//			}
//			break;
//			
//		case TouchEvent.UP : 
//			
//			focused = false;
//			touchDown = false;
//			invalidate();
//			break;
//			
//		case TouchEvent.CLICK : 
//			
//			execute();
//			break;
//		}
//		
//		return super.touchEvent(message);
//	}
	//Global이므로 MOVE로 필드를 빠져나간것을 감지 할 수 있음
//	protected boolean outOfBounds(TouchEvent message){
//		return message.getGlobalX(1) < getLeft() || message.getGlobalY(1) < getTop() 
//				|| message.getGlobalX(1) > getLeft() + getPreferredWidth()
//				|| message.getGlobalY(1) > getTop() + getPreferredHeight();
//	}

	
	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}

	//HighlightManager가 disable된다는건 focus도 안된다는 뜻이므로
	public boolean isFocusable() {
		return enabled;
	}
	
	public void execute() {};
	
	
	final class PaintField extends Field {
		
		private DjHighlightManager highlightManager;
		
		public PaintField(DjHighlightManager highlightManager) {
			this.highlightManager = highlightManager;
		}

		//원래 drawFocus()를 오버라이드해야하는걸로 추정되지만
		//Manager특성상 paint()를 오버라이드 했음
		protected void paint(Graphics graphics) {

			if (focused) {
				
				if (selectedColor == NOT_INIT || selected == false) {
					
					graphics.setColor(focusedColor);
					graphics.setGlobalAlpha(globalAlpha);
					graphics.fillRect(
							0,
							0, 
							highlightManager.getPreferredWidth(), 
							highlightManager.getPreferredHeight());

				} else  {
					
					graphics.setColor(selectedColor);
					graphics.setGlobalAlpha(globalAlpha);
					graphics.fillRect(
							0, 
							0, 
							highlightManager.getPreferredWidth(), 
							highlightManager.getPreferredHeight());
				}
			} 
		}
		
		protected void layout(int width, int height) {
			setExtent(width, height);
		}
	}
}
